package com.swak.consistency.tcc.handle;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;

import com.swak.consistency.core.execption.ConsistencyException;
import com.swak.consistency.core.handle.ConsistencyHandler;
import com.swak.consistency.core.invoke.Invoker;
import com.swak.consistency.tcc.context.TccContext;
import com.swak.consistency.tcc.role.Role;
import com.swak.consistency.tcc.role.TransRoler;
import com.swak.consistency.tcc.role.impls.TransCompleter;
import com.swak.consistency.tcc.role.impls.TransConsumer;
import com.swak.consistency.tcc.role.impls.TransInitiator;
import com.swak.consistency.tcc.role.impls.TransProvider;
import com.swak.consistency.tcc.role.impls.TransRetryer;
import com.swak.consistency.tcc.role.impls.TransTransmiter;
import com.swak.consistency.tcc.storage.TransLogStorage;
import com.swak.utils.Lists;

/**
 * 处理 Tcc 事件
 * 
 * @author DELL
 */
public class TccConsistencyHandler implements ConsistencyHandler<TccContext>, InitializingBean {

	@Autowired
	private TransLogStorage transLogStorage;
	@Autowired
	private Invoker invoker;

	/**
	 * 第一阶段的执行
	 */
	TransInitiator transInitiator;
	TransProvider transProvider;
	TransConsumer transConsumer;

	/**
	 * 第二阶段的发起
	 */
	TransCompleter transCompleter;

	/**
	 * 事务传输
	 */
	TransTransmiter transTransmiter;

	/**
	 * 事务补偿
	 */
	TransRetryer transRetryer;

	public TccConsistencyHandler() {
		transInitiator = new TransInitiator();
		transProvider = new TransProvider();
		transConsumer = new TransConsumer();
		transCompleter = new TransCompleter();
		transTransmiter = new TransTransmiter();
		transRetryer = new TransRetryer();
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		Lists.newArrayList(transInitiator, transConsumer, transProvider, transCompleter, transTransmiter, transRetryer)
				.forEach(roler -> {
					roler.init(transLogStorage, invoker);
				});
	}

	@Override
	public Object prepare(TccContext context) {
		Role role = context.getRole();
		return this.transRoler(role).doHandle(context);
	}

	@Override
	public Object transmit(TccContext context) {
		return transTransmiter.doHandle(context);
	}

	@Override
	public Object complete(TccContext context) {
		return transCompleter.doHandle(context);
	}

	@Override
	public void retry(TccContext context) {
		transRetryer.doHandle(context);
	}

	/**
	 * 当前事务参与者的角色
	 * 
	 * @return
	 */
	private TransRoler transRoler(Role role) {
		if (role == Role.INITIATOR) {
			return transInitiator;
		} else if (role == Role.PROVIDER) {
			return transProvider;
		} else if (role == Role.CONSUMER) {
			return transConsumer;
		}
		throw new ConsistencyException("不支持的事务状态:" + this.toString());
	}
}